﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.IO;

namespace curbside.XML
{
    public class XmlHelper
    {
        #region Old method

        /// <summary>
        /// Imports a XML node from text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="xmlDoc">The XML doc.</param>
        /// <returns></returns>
        public static XmlNode ImportXmlNodeFromText(string text, ref XmlDocument xmlDoc)
        {
            xmlDoc.LoadXml(text);
            return xmlDoc.FirstChild;
        }


        public static XmlDocument OpenAsXmlDocument(string filePath)
        {

            XmlTextReader reader = new XmlTextReader(filePath);
            reader.WhitespaceHandling = WhitespaceHandling.All;
            XmlDocument xmlDoc = new XmlDocument();
            //Load the file into the XmlDocument
            xmlDoc.Load(reader);
            //Close off the connection to the file.
            reader.Close();

            return xmlDoc;
        }

        /// <summary>
        /// creates a XmlAttribute with the specified name and value
        /// </summary>
        /// <param name="Xd">The xmldocument.</param>
        /// <param name="Name">The name of the attribute.</param>
        /// <param name="Value">The value of the attribute.</param>
        /// <returns>a XmlAttribute</returns>
        public static XmlAttribute addAttribute(XmlDocument Xd, string Name, string Value)
        {
            XmlAttribute temp = Xd.CreateAttribute(Name);
            temp.Value = Value;
            return temp;
        }

        /// <summary>
        /// Creates a text XmlNode with the specified name and value
        /// </summary>
        /// <param name="Xd">The xmldocument.</param>
        /// <param name="Name">The node name.</param>
        /// <param name="Value">The node value.</param>
        /// <returns>a XmlNode</returns>
        public static XmlNode addTextNode(XmlDocument Xd, string Name, string Value)
        {
            XmlNode temp = Xd.CreateNode(XmlNodeType.Element, Name, "");
            temp.AppendChild(Xd.CreateTextNode(Value));
            return temp;
        }

        /// <summary>
        /// Creates a cdata XmlNode with the specified name and value
        /// </summary>
        /// <param name="Xd">The xmldocument.</param>
        /// <param name="Name">The node name.</param>
        /// <param name="Value">The node value.</param>
        /// <returns>A XmlNode</returns>
        public static XmlNode addCDataNode(XmlDocument Xd, string Name, string Value)
        {
            XmlNode temp = Xd.CreateNode(XmlNodeType.Element, Name, "");
            temp.AppendChild(Xd.CreateCDataSection(Value));
            return temp;
        }


        /// <summary>
        /// Gets the value of a XmlNode
        /// </summary>
        /// <param name="n">The XmlNode.</param>
        /// <returns>the value as a string</returns>
        public static string GetNodeValue(XmlNode n)
        {
            if (n == null || n.FirstChild == null)
                return string.Empty;
            return n.FirstChild.Value;
        }

        /* The following helper methods are originally from http://prettycode.org/2009/05/07/hexadecimal-value-0x-is-an-invalid-character/ */

        /// <summary>
        /// Remove illegal XML characters from a string.
        /// </summary>
        public static string SanitizeXmlString(int nodeId, string xml, bool logOnError, string appendMessageToLog)
        {
            bool hasLogged = false;

            if (string.IsNullOrEmpty(xml))
            {
                return xml;
            }

            var buffer = new StringBuilder(xml.Length);

            foreach (char c in xml)
            {
                if (IsLegalXmlChar(c))
                {
                    buffer.Append(c);
                }
                else if (logOnError && !hasLogged)
                {
                    // Log.Add(LogTypes.Error, nodeId, String.Format("Illegal character ('{0}') have been removed{1}", c, appendMessageToLog));
                }
            }

            return buffer.ToString();
        }

        /// <summary>
        /// Whether a given character is allowed by XML 1.0.
        /// </summary>
        public static bool IsLegalXmlChar(int character)
        {
            return
            (
                 character == 0x9 /* == '\t' == 9   */        ||
                 character == 0xA /* == '\n' == 10  */        ||
                 character == 0xD /* == '\r' == 13  */        ||
                (character >= 0x20 && character <= 0xD7FF) ||
                (character >= 0xE000 && character <= 0xFFFD) ||
                (character >= 0x10000 && character <= 0x10FFFF)
            );
        }

        #endregion
    }
}
